﻿using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using System;
using System.Data;
using NHibernate.Tool.hbm2ddl;

namespace Data
{
    public interface IUnitOfWork : IDisposable
    {
        ISession Session { get; }
        void Commit();
        void Rollback();
    }

    public class UnitOfWork : IUnitOfWork
    {
        private readonly ISessionFactory _sessionFactory;
        private readonly ITransaction _transaction;

        public ISession Session { get; private set; }

        public UnitOfWork()
        {
            _sessionFactory = NHibernateHelper.SessionFactory;
            Session = _sessionFactory.OpenSession();
            Session.FlushMode = FlushMode.Auto;
            _transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
        }

        public void Dispose()
        {
            Session.Close();
        }

        public void Commit()
        {
            if (!_transaction.IsActive)
            {
                throw new InvalidOperationException("No active transation");
            }
            _transaction.Commit();
        }

        public void Rollback()
        {
            if (_transaction.IsActive)
            {
                _transaction.Rollback();
            }
        }
    }

    public static class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        public static ISessionFactory SessionFactory
        {
            get { return _sessionFactory ?? (_sessionFactory = CreateSessionFactory()); }
        }
        private static ISessionFactory CreateSessionFactory()
        {
            return Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008
                .ConnectionString(c => c
                    .Server("PC03")
                    .Database("DBADMIN")
                    .Username("sa")
                    .Password("2122")
                    ))
                .Mappings(m => m.FluentMappings.AddFromAssembly(typeof(NHibernateHelper).Assembly))
                .ExposeConfiguration(TreatConfiguration)
                .BuildConfiguration()
                .BuildSessionFactory();
        }
        private static void TreatConfiguration(NHibernate.Cfg.Configuration config)
        {
            var update = new SchemaUpdate(config);
            update.Execute(false, true);
        }
    }
}
